package org.example.annotation;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Component
@Aspect
//标识当前类是一个切面类 被自动代理识别
//等价于 <aop:aspect ref="myAspect">
public class MyAspect {
    //通知注解
    //基于5中不同的通知 提供了对应的注解
    //@通知类型(value="切点表达式") 如果仅配置value可以省略value

    //切点表达式的抽取
    //定义方法 使用切点表达式注解进行定义 方法名就是切点表达式的id
    @Pointcut("execution(* org.example.annotation.Target.*(..))")
    public void all(){}
    //当前切面类中 可以直接通过方法名()  all()进行切点表达式的使用
    //其他切面类 通过切面类.方法名() 进行使用 MyAspect.all()

    //前置通知注解
    @Before("all()")
    //等价于<aop:before method="before" pointcut="execution(* com.sqsf.annotation.*.*(..))"/>
    public void before(){
        System.out.println("前置通知");
    }

    //后置通知注解
    @After("MyAspect.all()")
    //等价于<aop:after method="after" pointcut="execution(* com.sqsf.annotation.*.*(..))"/>
    public void after(){
        System.out.println("后置通知");
    }

    //环绕通知注解
    @Around("MyAspect.all()")
    //等价于<aop:around method="around" pointcut="execution(* com.sqsf.annotation.*.*(..))"/>
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        System.out.println("环绕通知");
        Object proceed = joinPoint.proceed(args);
        System.out.println("环绕通知");
        return proceed;
    }
    //异常通知注解
    @AfterThrowing(value = "MyAspect.all()",throwing = "e")
    //<aop:after-throwing method="afterThrowing" pointcut="execution(* com.sqsf.aop.Target.*(..))" throwing="e"/>
    public void afterThrowing(Exception e){
        System.out.println("异常通知");
    }

    //返回通知注解
    @AfterReturning(value =  "MyAspect.all()",returning = "result")
    //<aop:after-returning method="afterReturning" pointcut="execution(* com.sqsf.aop.Target.*(..))" returning="result"/>
    public void afterReturning(Object result){
        System.out.println("返回通知");
    }
}